﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using DnPakExplorer.Forms;

namespace DnPakExplorer.Controls {
	[Designer(typeof(System.Windows.Forms.Design.ParentControlDesigner))]
	public partial class BagControlBase : ImagePanel {

		private int mMinGridMargin = 15;
		private Character mCharacter;
		private Rectangle mItemRect = new Rectangle(2, 2, 50, 50);
		private IItemUseTarget mItemUseTarget;
		private IItemUseTarget mDefaultItemUseTarget;
		private IBagItemFilter mFilter;
		private List<FiltedItem> mFiltedItems;
		private NameFilter mNameFilter;

		[Browsable(true)]
		public Image GridImage {
			get;
			set;
		}

		[Browsable(true)]
		public int MinGridMargin {
			get { return mMinGridMargin; }
			set {
				mMinGridMargin = value;
				Invalidate();
			}
		}

		[Browsable(true)]
		public Rectangle ItemRect {
			get {
				return mItemRect;
			}
			set {
				mItemRect = value;
				Invalidate(false);
			}
		}

		public Character Character {
			get { return mCharacter; }
			set {
				if (mCharacter != null) {
					mCharacter.BagPanel.OnBagItemChanged -= BagPanel_OnBagItemChanged;
					mCharacter.OnCharacterClosed -= mCharacter_OnCharacterClosed;
				}
				mCharacter = value;
				if (mCharacter != null) {
					mCharacter.BagPanel.OnBagItemChanged += BagPanel_OnBagItemChanged;
					mCharacter.OnCharacterClosed += mCharacter_OnCharacterClosed;
				}
				Invalidate(false);
			}
		}

		public void SetFilter(IBagItemFilter filter) {
			mFilter = filter;
			DonBagChanged();
			Invalidate(false);
		}

		public void SetFilterString(string filter) {
			if (string.IsNullOrEmpty(filter))
				mNameFilter = null;
			else
				mNameFilter = new NameFilter(filter);
			DonBagChanged();
			Invalidate(false);
		}

		public IUserItem GetItem(int index) {
			if (mFiltedItems != null) {
				return mFiltedItems[index].item;
			} else {
				return mCharacter.BagPanel[index];
			}
		}

		public int ItemCount {
			get {
				if (mFiltedItems != null) {
					return mFiltedItems.Count;
				} else {
					return mCharacter.BagPanel.BagSize;
				}
			}
		}
		

		public IItemUseTarget ItemUseTarget {
			get { return mItemUseTarget; }
			set {
				mItemUseTarget = value;
				if (mItemUseTarget == null) {
					mItemUseTarget = mDefaultItemUseTarget;
				}
			}
		}

		void mCharacter_OnCharacterClosed(object sender, EventArgs e) {
			Character = null;
			Form form = FindForm();
			if(form is PanelForm){
				form.Close();
			}
		}

		void DonBagChanged() {
			if (mFilter != null || mNameFilter != null) {
				BagPanel bag = Character.BagPanel;
				mFiltedItems = new List<FiltedItem>();
				for (int i=0; i<bag.BagSize; i++) {
					IUserItem item = bag[i];
					if ((mFilter == null || mFilter.Accept(item)) && (mNameFilter == null || mNameFilter.Accept(item)))
						mFiltedItems.Add(new FiltedItem() { item = item, indexInBag=i });
				}
			} else {
				mFiltedItems = null;
			}
		}

		void BagPanel_OnBagItemChanged(object sender, EventArgs e) {
			DonBagChanged();
			Invalidate(false);
		}

		public BagControlBase() {
			InitializeComponent();
			SetStyle(ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.AllPaintingInWmPaint|ControlStyles.UserPaint, true);
			mDefaultItemUseTarget = new DefaultItemUseTarget(this);
			ItemUseTarget = mDefaultItemUseTarget;
			this.Disposed += BagControlBase_Disposed;
		}

		void BagControlBase_Disposed(object sender, EventArgs e) {
			Character = null;
		}


		protected override void OnPaint(PaintEventArgs e) {
			if (GridImage != null) {
				BagPanel bag = mCharacter == null ? null : mCharacter.BagPanel;
				int hCount = (Width - Padding.Horizontal)/(GridImage.Width+MinGridMargin);
				int vCount = (Height - Padding.Vertical)/(GridImage.Height+MinGridMargin);
				int itemIndex = 0;
				for (int v=0; v<vCount; v++) {
					for (int h=0; h<hCount; h++) {
						Rectangle gridRect = new Rectangle(MinGridMargin+Padding.Left + h*(GridImage.Width+MinGridMargin),
							MinGridMargin+Padding.Top + v*(GridImage.Height+MinGridMargin),
							GridImage.Width,
							GridImage.Height);
						e.Graphics.DrawImage(GridImage,
							MinGridMargin+Padding.Left + h*(GridImage.Width+MinGridMargin),
							MinGridMargin+Padding.Top + v*(GridImage.Height+MinGridMargin),
							GridImage.Width,
							GridImage.Height);
						if (bag != null && itemIndex < ItemCount) {
							IUserItem item = GetItem(itemIndex);
							if (item != null) {
								Rectangle itemRect = new Rectangle(gridRect.X+ItemRect.X, gridRect.Y+ItemRect.Y, ItemRect.Width, ItemRect.Height);
								Util.DrawItemImage(item.iconId, itemRect, e.Graphics);
								Util.DrawItemBox(item.rank, itemRect, e.Graphics);
								Util.DrawItemTags(item, itemRect, e.Graphics);
							}
						}
						itemIndex ++;
					}
				}
			}
			base.OnPaint(e);
		}

		private void BagControlBase_MouseDown(object sender, MouseEventArgs e) {
			IUserItem item = ItemOfPosition(e.Location);
			if (e.Button == System.Windows.Forms.MouseButtons.Left) {
				if (item == null) {
					InfoOverlayForm.HideItem();
					WindowsUtil.MoveWindow(this.FindForm());
				} 
			}
		}

		private void BagControl_MouseMove(object sender, MouseEventArgs e) {
			IUserItem item = ItemOfPosition(e.Location);
			if (item != null) {
				InfoOverlayForm.ShowItem(item);
				Capture = true;
			} else {
				InfoOverlayForm.HideItem();
				Capture = false;
			}
		}

		private void BagControl_MouseClick(object sender, MouseEventArgs e) {
			IUserItem item = ItemOfPosition(e.Location);
			if (e.Button == System.Windows.Forms.MouseButtons.Right) {
				if (item != null) {
					if (ItemUseTarget != null) {
						ItemUseTarget.UseItem(Character.BagPanel, item);
					}
				}
			}
		}

		private IUserItem ItemOfPosition(Point point) {
			if (GridImage != null && Character != null) {
				int hCount = (Width - Padding.Horizontal)/(GridImage.Width+MinGridMargin);
				int vCount = (Height - Padding.Vertical)/(GridImage.Height+MinGridMargin);
				int h = (point.X - Padding.Left)/(GridImage.Width+MinGridMargin);
				int v = (point.Y - Padding.Top)/(GridImage.Height+MinGridMargin);
				int itemIndex = v*hCount + h;
				if (h < 0 || h >= hCount || v < 0 || v >= vCount 
					|| point.X < Padding.Left + h*(GridImage.Width+MinGridMargin) + MinGridMargin
					|| point.Y < Padding.Top + v*(GridImage.Height+MinGridMargin) + MinGridMargin
					|| itemIndex >= Character.BagPanel.BagSize)
					return null;
				return Character.BagPanel[itemIndex];
			}
			return null;
		}

		private void BagControl_MouseLeave(object sender, EventArgs e) {
			InfoOverlayForm.HideItem();
			Capture = false;
		}

		private void BagControl_MouseCaptureChanged(object sender, EventArgs e) {
			if (!Capture) {
				InfoOverlayForm.HideItem();
			}
		}

		class DefaultItemUseTarget : IItemUseTarget{
			private BagControlBase mControl;

			public DefaultItemUseTarget(BagControlBase control) {
				mControl = control;
			}

			public void UseItem(BagPanel bag, IUserItem item) {
				if (System.Windows.Forms.Control.ModifierKeys == Keys.Shift) {
					InfoOverlayForm.HideItem();
					new ItemEdtorForm(item).ShowDialog(mControl);
				} else if (bag.Character.EquipmentPanel.CanEquip(item)) {
					IUserItem[] oldItems = bag.Character.EquipmentPanel.Equip(item);
					bag.RemoveItem(item);
					if (oldItems != null) {
						foreach (IUserItem it in oldItems)
							bag.Character.BagPanel.AddItem(it);
					}
				}
			}
		}

		public interface IBagItemFilter {

			bool Accept(IUserItem item);
		}

		class FiltedItem{
			public IUserItem item;
			public int indexInBag;
		}

		public class CashItemFilter : IBagItemFilter{

			public bool Accept(IUserItem item) {
				return item == null || item.isCash;
			}
		}

		public class NormalItemFilter : IBagItemFilter {

			public bool Accept(IUserItem item) {
				return item == null || !item.isCash;
			}
		}

		public class NameFilter : IBagItemFilter {

			private string mPettern;

			public NameFilter(string pettern) {
				mPettern = pettern;
			}

			public bool Accept(IUserItem item) {
				if (string.IsNullOrEmpty(mPettern))
					return true;
				if (item != null && item.name.IndexOf(mPettern)>=0)
					return true;
				return false;
			}
		}


		public class DragonJewelItemFilter : IBagItemFilter {

			public bool Accept(IUserItem item) {
				return item == null || item.exchangType == ItemType.DragonJewel || item.exchangType == ItemType.SkillDragonJewel;
			}
		}

		public class ItemFilter : IBagItemFilter{
			public bool acceptNullItem = true;
			private ItemType[] mItemTypes;

			public ItemFilter(params ItemType[] types){
				mItemTypes = types;
			}

			public bool Accept(IUserItem item) {
				if (item == null) {
					return acceptNullItem;
				}
				for (int i=0; i<mItemTypes.Length; i++) {
					if (mItemTypes[i] == item.exchangType)
						return true;
				}
				return false;
			}
		}
	}
}
